package com.moyoutian.leetcode;

/**
 * 165. 比较版本号
 * <p>
 * 给你两个版本号 version1 和 version2 ，请你比较它们。
 * <p>
 * 版本号由一个或多个修订号组成，各修订号由一个 '.' 连接。每个修订号由 多位数字 组成，可能包含 前导零 。每个版本号至少包含一个字符。修订号从左到右编号，下标从 0 开始，最左边的修订号下标为 0 ，下一个修订号下标为 1 ，以此类推。例如，2.5.33 和 0.1 都是有效的版本号。
 * <p>
 * 比较版本号时，请按从左到右的顺序依次比较它们的修订号。比较修订号时，只需比较 忽略任何前导零后的整数值 。也就是说，修订号 1 和修订号 001 相等 。如果版本号没有指定某个下标处的修订号，则该修订号视为 0 。例如，版本 1.0 小于版本 1.1 ，因为它们下标为 0 的修订号相同，而下标为 1 的修订号分别为 0 和 1 ，0 < 1 。
 * <p>
 * 返回规则如下：
 * <p>
 * 如果 version1 > version2 返回 1，
 * 如果 version1 < version2 返回 -1，
 * 除此之外返回 0。
 * <p>
 * <p>
 * <p>
 * 示例 1：
 * <p>
 * 输入：version1 = "1.01", version2 = "1.001"
 * 输出：0
 * 解释：忽略前导零，"01" 和 "001" 都表示相同的整数 "1"
 * <p>
 * 示例 2：
 * <p>
 * 输入：version1 = "1.0", version2 = "1.0.0"
 * 输出：0
 * 解释：version1 没有指定下标为 2 的修订号，即视为 "0"
 * <p>
 * 示例 3：
 * <p>
 * 输入：version1 = "0.1", version2 = "1.1"
 * 输出：-1
 * 解释：version1 中下标为 0 的修订号是 "0"，version2 中下标为 0 的修订号是 "1" 。0 < 1，所以 version1 < version2
 * <p>
 * 示例 4：
 * <p>
 * 输入：version1 = "1.0.1", version2 = "1"
 * 输出：1
 * <p>
 * 示例 5：
 * <p>
 * 输入：version1 = "7.5.2.4", version2 = "7.5.3"
 * 输出：-1
 * <p>
 * 提示：
 * <p>
 * 1 <= version1.length, version2.length <= 500
 * version1 和 version2 仅包含数字和 '.'
 * version1 和 version2 都是 有效版本号
 * version1 和 version2 的所有修订号都可以存储在 32 位整数 中
 */
public class Demo165 {


    public static void main(String[] args) {
        String version1 = "0", version2 = "0";
        System.out.println(compareVersion(version1, version2));
    }

    /**
     * @param version1 版本号
     * @param version2 版本号
     * @return 如果 version1 > version2 返回 1，如果 version1 < version2 返回 -1，除此之外返回 0
     * <p>
     * 版本号由一个或多个修订号组成，各修订号由一个 '.' 连接。每个修订号由 多位数字 组成，可能包含 前导零 。每个版本号至少包含一个字符。修订号从左到右编号，下标从 0 开始，最左边的修订号下标为 0 ，下一个修订号下标为 1 ，以此类推。例如，2.5.33 和 0.1 都是有效的版本号。
     * 比较版本号时，请按从左到右的顺序依次比较它们的修订号。比较修订号时，只需比较 忽略任何前导零后的整数值 。也就是说，修订号 1 和修订号 001 相等 。如果版本号没有指定某个下标处的修订号，则该修订号视为 0 。例如，版本 1.0 小于版本 1.1 ，因为它们下标为 0 的修订号相同，而下标为 1 的修订号分别为 0 和 1 ，0 < 1 。
     */
    public static int compareVersion(String version1, String version2) {
        //当前正在扫描的索引下标
        int v1Index = 0;
        int v2Index = 0;

        while (v1Index < version1.length() && v2Index < version2.length()) {
            //v1的修订号，当前要比较的
            int v1V = 0;
            while (v1Index < version1.length() && isNumber(version1.charAt(v1Index))) {
                v1V = v1V * 10 + (version1.charAt(v1Index) - 48);
                v1Index++;
            }
            v1Index++;
            int v2V = 0;
            while (v2Index < version2.length() && isNumber(version2.charAt(v2Index))) {
                v2V = v2V * 10 + (version2.charAt(v2Index) - 48);
                v2Index++;
            }
            v2Index++;
            if (v1V != v2V) {
                return v1V > v2V ? 1 : -1;
            }
        }

        while (v1Index < version1.length()) {
            //v1的修订号，当前要比较的
            while (v1Index < version1.length() && isNumber(version1.charAt(v1Index))) {
                if (version1.charAt(v1Index) > 48) {
                    return 1;
                }
                v1Index++;
            }
            v1Index++;
        }
        while (v2Index < version2.length()) {
            //v1的修订号，当前要比较的
            while (v2Index < version2.length() && isNumber(version2.charAt(v2Index))) {
                if (version2.charAt(v2Index) > 48) {
                    return -1;
                }
                v2Index++;
            }
            v2Index++;
        }
        return 0;
    }


    /**
     * @param version1 版本号
     * @param version2 版本号
     * @return 如果 version1 > version2 返回 1，如果 version1 < version2 返回 -1，除此之外返回 0
     * <p>
     * 版本号由一个或多个修订号组成，各修订号由一个 '.' 连接。每个修订号由 多位数字 组成，可能包含 前导零 。每个版本号至少包含一个字符。修订号从左到右编号，下标从 0 开始，最左边的修订号下标为 0 ，下一个修订号下标为 1 ，以此类推。例如，2.5.33 和 0.1 都是有效的版本号。
     * 比较版本号时，请按从左到右的顺序依次比较它们的修订号。比较修订号时，只需比较 忽略任何前导零后的整数值 。也就是说，修订号 1 和修订号 001 相等 。如果版本号没有指定某个下标处的修订号，则该修订号视为 0 。例如，版本 1.0 小于版本 1.1 ，因为它们下标为 0 的修订号相同，而下标为 1 的修订号分别为 0 和 1 ，0 < 1 。
     */
    public static int compareVersion1(String version1, String version2) {
        int minLen = Math.min(version1.length(), version2.length());
        //当前正在扫描的索引下标
        int v1Index = 0;
        int v2Index = 0;

        while (v1Index < version1.length() && v2Index < version2.length()) {
            //v1的修订号，当前要比较的
            int v1V = 0;
            while (v1Index < version1.length() && isNumber(version1.charAt(v1Index))) {
                v1V = v1V * 10 + (version1.charAt(v1Index) - 48);
                v1Index++;
            }
            v1Index++;
            int v2V = 0;
            while (v2Index < version2.length() && isNumber(version2.charAt(v2Index))) {
                v2V = v2V * 10 + (version2.charAt(v2Index) - 48);
                v2Index++;
            }
            v2Index++;
            if (v1V != v2V) {
                return v1V > v2V ? 1 : -1;
            }
        }

        while (v1Index < version1.length()) {
            //v1的修订号，当前要比较的
            int v1V = 0;
            while (v1Index < version1.length() && isNumber(version1.charAt(v1Index))) {
                v1V = v1V * 10 + (version1.charAt(v1Index) - 48);
                v1Index++;
            }
            v1Index++;
            int v2V = 0;
            if (v1V != v2V) {
                return v1V > v2V ? 1 : -1;
            }
        }

        while (v2Index < version2.length()) {
            //v1的修订号，当前要比较的
            int v1V = 0;
            int v2V = 0;
            while (v2Index < version2.length() && isNumber(version2.charAt(v2Index))) {
                v2V = v2V * 10 + (version2.charAt(v2Index) - 48);
                v2Index++;
            }
            v2Index++;
            if (v1V != v2V) {
                return v1V > v2V ? 1 : -1;
            }
        }
        return 0;
    }

    /**
     * 判断字符是否是数字
     */
    public static boolean isNumber(char c) {
        return (48 <= c && c <= 57);
    }

    public static int getNumbers(String s, int index) {
        int re = 0;
        while (index < s.length() && isNumber(s.charAt(index))) {
            re = re * 10 + (s.charAt(index) - 48);
            index++;
        }
        return re;
    }
}
